package mongoUtil

import (
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
	"log"
	"strings"
	"time"
)

func ConnectToPool(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	o := options.Client().ApplyURI(uri)
	o.SetMaxPoolSize(num)
	client, err := mongo.Connect(ctx, o)
	if err != nil {
		return nil, err
	}

	return client.Database(name), nil
}

func CreatConn(username, password, ipAddr, port string) *mongo.Client {
	baseConfig := []string{"mongodb://", username, ":", password, "@", ipAddr, ":", port}
	var uri = strings.Join(baseConfig, "")
	client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
	if err != nil {
		panic(err)
	}
	err = isConSuccess(client)
	if err != nil {
		log.Fatalln(err)
	}
	return client
}
func CreatCon(username, password, host string) (*mongo.Client, error) {
	var uri = strings.Join([]string{"mongodb://", username, ":", password, "@", host}, "")
	clientOptions := options.Client()
	client, err := mongo.Connect(context.TODO(), clientOptions.ApplyURI(uri).SetTimeout(4*time.Second))
	if err != nil {
		log.Fatalln(err)
		return nil, err
	}
	err = isConSuccess(client)
	if err != nil {
		log.Fatalln(err)
		return nil, err

	}
	return client, nil
}
func CreatConnWithOpt(clientOpts *options.ClientOptions) *mongo.Client {
	client, err := mongo.Connect(context.TODO(), clientOpts)
	if err != nil {
		log.Fatalln(err)
	}
	err = isConSuccess(client)
	if err != nil {
		log.Fatalln(err)
	}
	return client
}
func isConSuccess(client *mongo.Client) error {
	if err := client.Ping(context.TODO(), readpref.Primary()); err != nil {
		return err
	}
	log.Println("Successfully connected and pinged.")
	return nil
}
func GetOptions(username, password, host string) *options.ClientOptions {
	credential := options.Credential{
		AuthMechanism: "SCRAM-SHA-1",
		AuthSource:    "admin",
		Username:      username,
		Password:      password,
	}
	_clientOptions := options.Client().
		SetTimeout(5 * time.Second).
		SetAuth(credential).
		ApplyURI(strings.Join([]string{"mongodb://", host}, ""))
	return _clientOptions
}

func CreateCollection(db *mongo.Database, collection string, format bson.M) *mongo.Collection {
	validator := bson.M{
		"$jsonSchema": format,
	}
	opts := options.CreateCollection().SetValidator(validator)
	err := db.CreateCollection(context.TODO(), collection, opts)
	if err != nil {
		panic(err)
		return nil
	}
	return db.Collection(collection)
}

func CreateIndexUnique(coll *mongo.Collection, key bson.M, opts ...*options.CreateIndexesOptions) {
	indexModel := mongo.IndexModel{
		Keys:    key,
		Options: options.Index().SetUnique(true),
	}
	name, err := coll.Indexes().CreateOne(context.TODO(), indexModel, opts...)
	if err != nil {
		panic(err)
	}
	log.Println("Name of Index Created: ", name)

}
